package com.softer.wxzj.common.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.util.Map;

/**
 *    
 *  @ClassName: CombineEntityUtil   
 *  @Description: 合并同类型实体类工具类
 *  @Author:  zcz   
 *  @CreateDate: 2019-06-13     
 *  
 */
@Slf4j
@Component
public class CombineEntityUtil<T> {
    /**
     * sourceBean中非null字段值会并入targetBean中
     * @param sourceBean
     * @param targetBean
     * @return
     */
    public T combineEntity(T sourceBean, T targetBean) {
        Class sourceBeanClass = sourceBean.getClass();
        Class targetBeanClass = targetBean.getClass();
        Field[] sourceFields = sourceBeanClass.getDeclaredFields();
        Field[] targetFields = targetBeanClass.getDeclaredFields();
        for (int i = 0; i < sourceFields.length; i++) {
            Field sourceField = sourceFields[i];
            if (Modifier.isStatic(sourceField.getModifiers())) {
                continue;
            }
            Field targetField = targetFields[i];
            if (Modifier.isStatic(targetField.getModifiers())) {
                continue;
            }
            sourceField.setAccessible(true);
            targetField.setAccessible(true);
            try {
                //非null执行合并
                if (sourceField.get(sourceBean) != null) {
                    Class<?> fieldTypeClass = sourceField.getType();
                    Object value = null;
                    // TODO
                    if (!"".equals(sourceField.get(sourceBean))) {
                        value = convertValType(sourceField.get(sourceBean), fieldTypeClass);
                    }
                    targetField.set(targetBean, value);
                }
            } catch (IllegalArgumentException | IllegalAccessException e) {
                log.error("IllegalArgumentException错误信息:()", e.getMessage(), e);
            }
        }
        return targetBean;
    }

    /**
     * map合并到实体类中
     * @param map
     * @param targetBean
     * @return
     * @throws Exception
     */
    public T mapCombineEntity(Map<String, Object> map, T targetBean) {
        Class<?> clazz = targetBean.getClass();
        if (map != null && map.size() > 0) {
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                //属性名
                String propertyName = entry.getKey();
                Object value = entry.getValue();
                String setMethodName = "set"
                        + propertyName.substring(0, 1).toUpperCase()
                        + propertyName.substring(1);
                try {
                    Field field = getClassField(clazz, propertyName);
                    if (field == null) {
                        continue;
                    }
                    Class<?> fieldTypeClass = field.getType();
                    value = convertValType(value, fieldTypeClass);
                    try {
                        clazz.getMethod(setMethodName, field.getType()).invoke(targetBean, value);
                    } catch (NoSuchMethodException e) {
                        log.error("NoSuchMethodException错误信息:()", e.getMessage(), e);
                    }
                } catch (Exception e) {
                    log.error("错误信息:()", e.getMessage(), e);
                }
            }
        }
        return targetBean;
    }

    /**
     * 将Object类型的值，转换成bean对象属性里对应的类型值
     * @param value Object对象值
     * @param fieldTypeClass 属性的类型
     * @return 转换后的值
     */
    private static Object convertValType(Object value, Class<?> fieldTypeClass) {
        Object retVal;
        if (Long.class.isAssignableFrom(fieldTypeClass)
                || long.class.isAssignableFrom(fieldTypeClass)) {
            retVal = Long.parseLong(value.toString());
        } else if (Integer.class.isAssignableFrom(fieldTypeClass)
                || int.class.isAssignableFrom(fieldTypeClass)) {
            retVal = Integer.parseInt(value.toString());
        } else if (Float.class.isAssignableFrom(fieldTypeClass)
                || float.class.isAssignableFrom(fieldTypeClass)) {
            retVal = Float.parseFloat(value.toString());
        } else if (Double.class.isAssignableFrom(fieldTypeClass)
                || double.class.isAssignableFrom(fieldTypeClass)) {
            retVal = Double.parseDouble(value.toString());
        } else if (BigDecimal.class.isAssignableFrom(fieldTypeClass)) {
            if (value != null) {
                retVal = BigDecimal.valueOf(Double.parseDouble(value.toString()));
            } else {
                retVal = BigDecimal.ZERO;
            }
        } else {
            retVal = value;
        }
        return retVal;
    }

    /**
     * 获取指定字段名称查找在class中的对应的Field对象(包括查找父类)
     * @param clazz 指定的class
     * @param fieldName 字段名称
     * @return Field对象
     */
    private static Field getClassField(Class<?> clazz, String fieldName) {
        if (clazz.isAssignableFrom(Object.class)) {
            return null;
        }
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            if (field.getName().equals(fieldName)) {
                return field;
            }
        }
        Class<?> superClass = clazz.getSuperclass();
        if (superClass != null) {
            return getClassField(superClass, fieldName);
        }
        return null;
    }
}
